package com.ics.cmsadmin.frame.interceptor;

import com.ics.cmsadmin.frame.core.annotation.Authorize;
import com.ics.cmsadmin.frame.core.bean.ApiResponse;
import com.ics.cmsadmin.frame.core.enums.ApiResultEnum;
import com.ics.cmsadmin.frame.core.enums.AuthorizeEnum;
import com.ics.cmsadmin.frame.utils.HttpUtils;
import com.ics.cmsadmin.modules.auth.service.AuthorizeService;
import com.ics.cmsadmin.modules.sso.LoginInfo;
import com.ics.cmsadmin.modules.sso.utils.SsoUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 登陆拦截器
 * Created by Administrator on 2017/7/28.
 */
@Component
public class AuthorizeInterceptor extends HandlerInterceptorAdapter {

    @Resource
    private AuthorizeService authorizeService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        LoginInfo loginUser = SsoUtils.getLoginUser(request);
        if (loginUser == null){
            HttpUtils.setJsonDataResponse(response, new ApiResponse(ApiResultEnum.LOGIN_PAST_DUE), 403);
            return false;
        }
        List<String> userAuthorizes = authorizeService.listAuthorizesByUserId(loginUser.getLoginId());
        return checkUserAuthorize(handler, userAuthorizes, response);
    }

    private boolean checkUserAuthorize(Object handler, List<String> userAuthorizes, HttpServletResponse response) {
        // 1. 如果请求不是方法请求的话,则通过
        if (!(handler instanceof HandlerMethod)){
            return true;
        }
        Authorize authorize =  ((HandlerMethod) handler).getMethodAnnotation(Authorize.class);
        // 2. 如果注解没有权限定义的话,则不通过
        if (authorize == null){
            HttpUtils.setJsonDataResponse(response, new ApiResponse(ApiResultEnum.OPERATION_FORBIDDEN), 403);
            return false;
        }
        // 3. 如果有value有定义的话,则用户必须包含value所有的权限
        Set<AuthorizeEnum> must = Arrays.asList(authorize.value()).stream().collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(must)){
            Optional<AuthorizeEnum> first = must.stream().filter(authorizeEnum ->
                    !userAuthorizes.contains(authorizeEnum.name())
            ).findFirst();
            if (first.isPresent()){
                HttpUtils.setJsonDataResponse(response,
                        new ApiResponse(ApiResultEnum.OPERATION_FORBIDDEN,"您没有 '" + first.get().getDescription() + "' 的操作权限"), 403);
                return false;
            }
            return true;
        }

        // 4. 如果value为空,则any生效,用户只需要包含any中其中一个权限,则通过
        Set<AuthorizeEnum> any = Arrays.asList(authorize.any()).stream().collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(any)){
            long count = any.stream().filter(authorizeEnum -> userAuthorizes.contains(authorizeEnum.name())).count();
            if (count > 0){
                return true;
            }else{
                Optional<AuthorizeEnum> first = any.stream().findFirst();
                HttpUtils.setJsonDataResponse(response,
                        new ApiResponse(ApiResultEnum.OPERATION_FORBIDDEN, "您没有 '" + first.get().getDescription() + "' 的操作权限"), 403);
                return false;
            }
        }
        // 5. 如果must和any都为空,则说明该操作不需要权限
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

}
